﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Milan.Deploy
{
	/// <summary>
	/// The Upload routines for the client class
	/// </summary>
	public partial class Client
	{
		public Client(Package package) : this()
		{
			m_package = package;
		}
		/// <summary>
		/// Puts a file to the server using the postURL service.
		/// Name = source file on disk, Value = relative destination on server
		/// </summary>
		/// <param name="source">path to local source file</param>
		/// <param name="destination">Relative destination file</param>
		public void PutFileOnce(Uri uploadScriptUri, string source, string destination, bool compress = false)
		{
			NameValueCollection vars = SetPostVars(OpCodes.upload, destination);
			if (compress)
				Milan.Net.Upload.PostFileCompressed(uploadScriptUri, source, vars);
			else
				Milan.Net.Upload.PostFile(uploadScriptUri, source, vars);
		}
		/// <summary>
		/// This sets the release type of this version, by changing it here locally and uploading
		/// the version file.
		/// </summary>
		/// <param name="releaseType"></param>
		public void SetReleaseType(ReleaseType releaseType)
		{
			foreach (var uploadScriptUri in UploadScriptUris)
			{
				SetReleaseTypeOnce(uploadScriptUri, releaseType);
			}
		}
		private void SetReleaseTypeOnce(Uri uploadScriptUri, ReleaseType releaseType)
		{
			NameValueCollection postVars = SetPostVars(OpCodes.setreleasetype, null);
			postVars.Add("type",releaseType.ToString());
			Milan.Net.Upload.PostVarsOnly(uploadScriptUri, postVars);
		}
		public void UploadEntireProductIfNeeded()
		{
			foreach (var uploadScriptUri in UploadScriptUris)
			{
				Version remoteVersion = GetLatestVersionInfo(uploadScriptUri);
				if ((remoteVersion != null) && (remoteVersion < m_package.GetProductVersion()))
				{
					try
					{
						UploadEntireProductOnce(uploadScriptUri);
					}
					catch (System.Exception)
					{
					}
				}
			}
		}
		/// <summary>
		/// Uploads the entire product to the servers using the upload scripts.
		/// </summary>
		/// <param name="fileList">List the files</param>
		/// <param name="releaseType"></param>
		public void UploadEntireProduct()
		{
			foreach (var uploadScriptUri in UploadScriptUris)
			{
				try
				{
					UploadEntireProductOnce(uploadScriptUri);
				}
				catch (System.Exception)
				{
				}
			}
		}
		public void UploadEntireProductOnce(Uri uploadScriptUri)
		{
			// Put each file up
			StringBuilder fileList = new StringBuilder();
			StringBuilder linkList = new StringBuilder();
			try
			{
				foreach (var file in m_package.Files)
				{
					PutFileOnce(uploadScriptUri, file.Source, file.Destination + ".deploy", true);
					fileList.AppendLine(file.Destination + ".deploy");
				}
				if (m_package.Links.Count > 0)
				{
					foreach (var link in m_package.Links)
						linkList.AppendLine("\"" + link.Description + "\",\"" + link.Target + "\",\"" + link.Arguments + "\",\"" + link.Shortcut + "\",\"" + link.IconLocation + "\",0,\"" + link.CurrentDirectory + "\"");
					fileList.AppendLine("links.txt");
				}
				// Optional Install command
				if (InstallCommand != null)
				{
					Milan.Net.Upload.PostTextAsFile(uploadScriptUri, InstallCommand, "install.bat", SetPostVars(OpCodes.upload, "install.bat"));
					fileList.AppendLine("install.bat");
				}

				// Optional UninstallCommand command
				if (UninstallCommand != null)
				{
					Milan.Net.Upload.PostTextAsFile(uploadScriptUri, UninstallCommand, "uninstall.bat", SetPostVars(OpCodes.upload, "uninstall.bat"));
					fileList.AppendLine("uninstall.bat");
				}

				// Optional Test command
				if (TestCommand != null)
				{
					Milan.Net.Upload.PostTextAsFile(uploadScriptUri, TestCommand, "test.bat", SetPostVars(OpCodes.upload, "test.bat"));
					fileList.AppendLine("test.bat");
				}

				// Copy up the files.txt file
				Milan.Net.Upload.PostTextAsFile(uploadScriptUri, fileList.ToString(), "files.txt", SetPostVars(OpCodes.upload, "files.txt"));

				// Copy up the links.txt file
				if(m_package.Links.Count>0)
					Milan.Net.Upload.PostTextAsFile(uploadScriptUri, linkList.ToString(), "links.txt", SetPostVars(OpCodes.upload, "links.txt"));

				// Finally, set the release type, if we have made it this far.
				SetReleaseTypeOnce(uploadScriptUri, ReleaseType.Last);
			}
			catch (System.Net.WebException)
			{
				// We just ignore errors
			}
		}
		/// <summary>
		/// Upload a log file
		/// </summary>
		/// <param name="filePath"></param>
		public void UploadLogFile(string filePath)
		{
			OpCodes opcodes = OpCodes.log;
			if (Path.GetExtension(filePath) == ".err")
				opcodes = OpCodes.err;
			if (Path.GetExtension(filePath) == ".dmp")
				opcodes = OpCodes.dmp;
			var postData = SetPostVars(opcodes, Path.GetFileName(filePath));
			foreach( var scriptUri in UploadScriptUris )
				Milan.Net.Upload.PostFile(scriptUri, filePath, postData);
		}

		/// <summary>
		/// Sends an email
		/// </summary>
		/// <param name="destination">Destination list for email</param>
		/// <param name="subject"></param>
		/// <param name="message"></param>
		/// <param name="fileName">Optional file name</param>
		/// <returns>true if success, false if not. Does not throw exception normally</returns>
		public bool SendEmail(string destination, string subject,string message,string fileName = null)
		{
			string returns = "er";
			var postData = SetPostVars(OpCodes.email, destination);
			postData["subject"] = subject; 
			postData["message"] = message;
			foreach (var scriptUri in UploadScriptUris)
			{
				if (fileName != null)
					returns = Milan.Net.Upload.PostFile(scriptUri, fileName, postData);
				else
					returns = Milan.Net.Upload.PostVarsOnly(scriptUri, postData);
			}
			return returns.Substring(0,2)=="ok";
		}

		private Package m_package;
	}
}
